//
//  CWCustomPresentAnnimation.m
//  01-自定义转场动画
//
//  Created by chenWei on 2017/5/13.
//  Copyright © 2017年 陈伟. All rights reserved.
//

#import "CWCustomPresentAnnimation.h"


@interface CWCustomPresentAnnimation ()<UIViewControllerAnimatedTransitioning, CAAnimationDelegate>

//是否是转场
@property(nonatomic, assign) BOOL isPresent;

//转场上下文
@property(nonatomic, weak)id<UIViewControllerContextTransitioning> transitionContext;

@end

@implementation CWCustomPresentAnnimation

#pragma mark - UIViewControllerTransitioningDelegate代理方法 告诉系统谁提供/解除转场
//由谁负责提供转场
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
    self.isPresent = YES;
    return self;
}

//谁负责解除转场
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{   self.isPresent = NO;
    return self;
}

#pragma mark - UIViewControllerAnimatedTransitioning转场动画协议
//转场动画时长
- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext;
{
    return 0.8;
}

// MARK:- 真正执行转场动画的地方
/*
 transitionContext: 负责提供转场过程中的一切细节
 转场上下文会强引用控制器，需注意循环引用
 */
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    //1.获取转场上下文的容器视图
    UIView *containView = transitionContext.containerView;
    
    //2.获取转场上下文的目标视图  fromView 是presented 控制器
    UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
    // toView 是 presenting 控制器
    UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
    
    UIView *view = self.isPresent ? toView : fromView;
    
    //3.将目标视图添加到容器视图中
    [containView addSubview:view];
    
    //4.执行动画
    [self animationWithView:view];
    
    
    //记录转场上下文
    self.transitionContext = transitionContext;
}


#pragma mark - CAAnimationDelegate动画代理
//动画结束
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    //动画完成之后解除转场
    [self.transitionContext completeTransition:YES];
    
}


#pragma mark - 执行动画
- (void)animationWithView:(UIView *)view
{
    //1.创建形状图层 shapeLayer
    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc]init];
    
    //2.创建圆形贝塞尔路径
    CGFloat screenWidth = view.frame.size.width;
    CGFloat screenHeight = view.frame.size.height;
    
    //圆距屏幕间距
    CGFloat margin = 20;
    //圆形半径
    CGFloat coradius = 25;
    
    //============创建起始圆==============
    CGRect startRect = CGRectMake(screenWidth - margin - coradius*2, margin, coradius*2, coradius*2);
    //创建起始贝塞尔路径
    UIBezierPath *startBezierPath = [UIBezierPath bezierPathWithOvalInRect:startRect];
    
    
    //============创建结束圆==============
    //结束圆半径
    CGFloat endRadius = sqrt(screenWidth*screenWidth + screenHeight*screenHeight);
    //使用缩进矩形创建圆的外接矩形， 参数1：起始圆  参数2：正就往里缩，负就往外扩
    CGRect endRect = CGRectInset(startRect, -endRadius, -endRadius);
    UIBezierPath *endBezierPath = [UIBezierPath bezierPathWithOvalInRect:endRect];
    
    
    //3.设置形状图层的填充颜色
    shapeLayer.fillColor = [UIColor redColor].CGColor;
    
    //4.设置绘制好的贝塞尔路径为绘制圆的路径
    shapeLayer.path = startBezierPath.CGPath;
    
    //5.设置shapeLayer为控制器视图的遮罩图层
    //设置 mask遮罩图层：1.裁切图层，让图层只能看见shapeLayer形状的区域； 2.设置遮罩图层之后，填充颜色就会无效
    view.layer.mask = shapeLayer;
    
    //将shapeLayer添加到控制器视图图层上,  addSublayer是在当前图层上添加一个形状的图层区域
    //[view.layer addSublayer:shapeLayer];
    
    
    //6.使用核心动画实现 layer 图层的动画
    [self animationWithStartPath:startBezierPath EndPath:endBezierPath ShapeLayer:shapeLayer];
    
    
    
}

//MARK: - 实现核心动画
- (void)animationWithStartPath:(UIBezierPath *)startPath EndPath:(UIBezierPath *)endPath ShapeLayer:(CAShapeLayer *)shapeLayer
{
    //1.创建核心动画  参数：动画改变的值
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
    
    //2.动画基本属性
    animation.duration = [self transitionDuration:self.transitionContext];
    
    //设置代理
    animation.delegate = self;
    
    
    //3.动画 开始值和结束值
    //如果是 present，动画是从小圆到大圆；如果是dismiss，动画是从大圆到小圆
    if (self.isPresent == YES) {
        animation.fromValue = (__bridge id _Nullable)(startPath.CGPath);
        animation.toValue = (__bridge id _Nullable)(endPath.CGPath);
    }else
    {
        animation.fromValue = (__bridge id _Nullable)(endPath.CGPath);
        animation.toValue = (__bridge id _Nullable)(startPath.CGPath);
    }
    
    
    //4.设置动画执行完不恢复
    animation.removedOnCompletion = NO;
    //设置填充模式
    animation.fillMode = kCAFillModeForwards;
    
    
    //5.执行动画，谁要动画就把动画添加到谁身上
    [shapeLayer addAnimation:animation forKey:nil];
    
}










@end
